﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;

namespace cs499.Database
{
    public class ListOfDepartment
    {
        public static Department CreateOrGetDepartment(String Name, String Code)
        {
            Model1Container db = new Model1Container();
            Department deptocreate=db.Set<Department>().FirstOrDefault(dep => (dep.Name == Name || dep.Code == Code));
            if (deptocreate == null) 
            {
                deptocreate = new Department();
                deptocreate.Code = Code;
                deptocreate.Name = Name;
                db.Set<Department>().Add(deptocreate);
                db.SaveChanges();
                return deptocreate;
            }
            else {
                return deptocreate;
            }
        }
        public static Department CreateDepartment(String Name, String Code)
        {
            Model1Container db = new Model1Container();
            Department deptocreate = db.Set<Department>().FirstOrDefault(dep => (dep.Name == Name || dep.Code == Code));
            if (deptocreate == null)
            {
                deptocreate = new Department();
                deptocreate.Code = Code;
                deptocreate.Name = Name;
                db.Set<Department>().Add(deptocreate);
                db.SaveChanges();
                return deptocreate;
            }
            else
            {
                return null;
            }
        }
        public static Department GetDepartment(String Name = "", String Code = "", int ID = -1)
        {
            if(Name=="" && Code=="" && ID==-1)return null;
            Model1Container db = new Model1Container();
            Department deptoget = db.Set<Department>().Include("Courses").Include("FacultyMembers").Include("Places").Include("Schedule").FirstOrDefault(dep => (dep.Name == Name || dep.Code == Code || dep.Id == ID));
            return deptoget;
        }
        public static bool DeleteDepartment(String Name = "", String Code = "", int ID = -1)
        {
            if (Name == "" && Code == "" && ID == -1) return false;
            Model1Container db = new Model1Container();
            Department deptodelete = db.Set<Department>()
                .Include("Courses")
                .Include("Places")
                .Include("FacultyMembers")
                .Include("Schedule")
                .FirstOrDefault(dep => (dep.Name == Name || dep.Code == Code || dep.Id == ID));
            if (deptodelete == null)
            {
                return false;
            }
            else
            {
                foreach(Course delcourse in deptodelete.Courses)
                {
                    delcourse.Delete();
                }
                foreach (Place delplace in deptodelete.Places)
                {
                    delplace.Delete();
                }
                foreach (Faculty faculty in deptodelete.FacultyMembers)
                {
                    faculty.Delete();
                }
                if(deptodelete.Schedule != null)
                {
                    deptodelete.Schedule.Delete();
                }
                db = new Model1Container();
                deptodelete = db.Set<Department>()
                    .FirstOrDefault(dep => (dep.Name == Name || dep.Code == Code || dep.Id == ID));
                if (deptodelete == null)
                {
                    return false;
                }
                db.Set<Department>().Remove(deptodelete);
                db.SaveChanges();
                return true;
            }
        }
        public static bool TimeSlotExists(TimeSlot timeslot)
        {
            if (timeslot == null) return false;
            Model1Container db = new Model1Container();
            TimeSlot tmslot = db.Set<TimeSlot>().FirstOrDefault(timeslottofind => timeslottofind.Days == timeslot.Days && timeslottofind.StartTime == timeslot.StartTime && timeslottofind.Length == timeslot.Length);
            if (tmslot == null) return false;
            else return true;
        }

        public static TimeSlot CreateTimeSlot(TimeSlot timeslot)
        {
            Model1Container db = new Model1Container();
            if (TimeSlotExists(timeslot)) return null;
            timeslot = db.Set<TimeSlot>().Add(timeslot);
            db.SaveChanges();
            return timeslot;
        }

        public static TimeSlot GetTimeSlot(TimeSpan? startTime = null, int length = -1, DayOfWeek days = 0, int ID = -1)
        {
            if (startTime == null && length == -1 && days == 0 && ID == -1) return null;

            Model1Container db = new Model1Container();

            TimeSlot timeSlot = db.Set<TimeSlot>().FirstOrDefault(timeSlotToFind => timeSlotToFind.Id == ID || (timeSlotToFind.StartTime == startTime && timeSlotToFind.Length == length && timeSlotToFind.Days == days));
            return timeSlot;
        }

        public static bool DeleteTimeSlot(int ID)
        {
            Model1Container db = new Model1Container();

            TimeSlot timeSlot = db.Set<TimeSlot>().FirstOrDefault(timeSlotToFind => timeSlotToFind.Id == ID);
            return timeSlot.Delete();
        }

        public static List<MembershipUser> GetUsersInDepartment(Int32 departmentid)
        {
            List<MembershipUser> retlist = new List<MembershipUser>();
            Model1Container db = new Model1Container();
            List<Faculty> facultyindepartment = db.Set<Faculty>().Where(Facultytofind => Facultytofind.DepartmentID == departmentid).ToList();
            foreach (Faculty fac in facultyindepartment)
            {
                MembershipUser tempuser = Membership.GetUser(fac.aspnet_userID);
                if (tempuser != null) retlist.Add(tempuser);
            }

            return retlist;
        }

        public static bool DeleteUserinDepartment(Guid aspfacultymemberid)
        {
            MembershipUser facultymember = Membership.GetUser(aspfacultymemberid);
            if (facultymember == null) return false;
                
            Model1Container db = new Model1Container();
            Faculty newFaculty = db.Set<Faculty>().FirstOrDefault(Facultytofind => Facultytofind.aspnet_userID == (Guid)facultymember.ProviderUserKey);
            
            return newFaculty.Delete();
        }

        public static List<Course> GetAvailableCourses(Int32 departmentid)
        {
            List<Course> retlist = new List<Course>();
            Model1Container db = new Model1Container();
            List<Course> coursesindepartment = db.Set<Course>()
                .Include("CourseInstances")
                .Include("CourseInstances.PreferredBy")//for scheduling change to taughtby
                .Where(coursetofind => coursetofind.DepartmentId == departmentid).ToList();
            foreach(Course tempcourse in coursesindepartment)
            {
                int facprefnums = 0;
                foreach (CourseInstance tempci in tempcourse.CourseInstances)
                {
                    if (tempci.PreferredBy != null) facprefnums++;//for scheduling change to taughtby
                }
                if (facprefnums < tempcourse.NumberOfSections) retlist.Add(tempcourse);
            }
            return retlist;
        }
        public static int timeslotsleftinroom(int roomid)
        {
            int retval = 1;
            //TODO: forward analyze time slots left in the room to see if this is a valid room
            return retval;
        }
        public static List<Room> GetAvailableRooms(Int32 courseid)
        {
            List<Room> retlist = new List<Room>();
            Model1Container db = new Model1Container();
            Course course = db.Set<Course>()
                .Include("PlaceRequirements")
                .Include("CourseInstances")
                .FirstOrDefault(c => c.Id == courseid);
            if (course == null) return retlist;
            if (course.PlaceRequirements.Count > 0)
            {
                if (course.PlaceRequirements.OfType<Room>().ToList().Count == 0)
                {
                    foreach(Building _building in course.PlaceRequirements.OfType<Building>().ToList())
                    {
                        Building dbbuilding = db.Set<Building>().Include("Rooms").FirstOrDefault(build => build.Id == _building.Id);

                        foreach (Room temproom in dbbuilding.Rooms)
                        {
                            if (timeslotsleftinroom(temproom.Id) > 0)
                            {
                                retlist.Add(temproom);
                            }
                        }
                    }
                }
                else
                {
                    foreach (Room temproom in course.PlaceRequirements.OfType<Room>().ToList())
                    {
                        if (timeslotsleftinroom(temproom.Id) > 0)
                        {
                            retlist.Add(temproom);
                        }
                    }
                }
            }
            else
            {
                List<Room> departmentrooms = db.Set<Room>().Where(rm => rm.DepartmentId == course.DepartmentId).ToList();
                foreach (Room temproom in departmentrooms)
                {
                    if (timeslotsleftinroom(temproom.Id) > 0)
                    {
                        retlist.Add(temproom);
                    }
                }
            }
            return retlist;
        }

        public static List<TimeSlot> GetAvailableTimeSlots(int roomid, int facultyid)//if facultyid == -1 use current loggedin facultymember
        {//returns list of time slots during which current faculty member is not busy and room is not busy
            List<TimeSlot> retlist = new List<TimeSlot>();
            Model1Container db = new Model1Container();
            Room inroom = db.Set<Room>()
                .Include("CourseInstances")
                .Include("CourseInstances.PreferredBy")//for scheduling add additional include for taughtby
                .Include("CourseInstances.Schedule")
                .Include("CourseInstances.TimeSlot")
                .FirstOrDefault(rm => rm.Id == roomid);
            if (inroom == null) return retlist;
            List<TimeSlot> timeslots = db.Set<TimeSlot>()
                .Include("CourseInstances").ToList();

            bool isvalid=true;
            foreach(TimeSlot timetovalidate in timeslots){
                isvalid = true;
                foreach (CourseInstance ci in inroom.CourseInstances )
                {
                    if (ci.Schedule != null || ci.PreferredBy == null) continue;//true if not a preference  //for scheduling change continue to logic and add else which continues
                    
                    if(timetovalidate.OverlapsWith(ci.TimeSlot))
                    {
                        isvalid=false;
                        break;
                    }
                }
                if (isvalid)
                {
                    if (facultyid == -1)//use current user
                    {
                        MembershipUser tempuser = Membership.GetUser(HttpContext.Current.User.Identity.Name);
                        Database.Faculty currentfaculty;
                        if (HttpContext.Current.Session["CurrentDepartmentId"] != null)
                        {
                            int CurrentDepartmentId = (int)HttpContext.Current.Session["CurrentDepartmentId"];
                            Department CurrentDepartment = ListOfDepartment.GetDepartment(ID: CurrentDepartmentId);
                            currentfaculty = CurrentDepartment.GetFaculty((Guid)tempuser.ProviderUserKey);
                            if (currentfaculty != null) facultyid = currentfaculty.Id;
                        }
                    }
                    cs499.Database.Faculty faculty = db.Set<Faculty>()
                        .Include("PreferredInstances")//for scheduling change to CourseInstances
                        .Include("PreferredInstances.TimeSlot")
                        .FirstOrDefault(fac => fac.Id == facultyid);
                    if (faculty != null ){//on error skip faculty check
                        foreach (CourseInstance ci in faculty.PreferredInstances)
                        {
                            if (timetovalidate.OverlapsWith(ci.TimeSlot))
                            {
                                isvalid = false;
                                break;
                            }
                        }
                    }
                    if (isvalid)
                    {
                        retlist.Add(timetovalidate);
                    }
                }
            }

            return retlist;
        }
    }
}